Adam

使用 Adam 算法更新参数权重。支持 Nesterov 动量。

算法逻辑如下:

\[\begin{split}m_t = m_{t-1} + (g_t - m_{t-1}) \cdot (1 - \beta_1) \\ v_t = v_{t-1} + (g_t^2 - v_{t-1}) \cdot (1 - \beta_2) \\ \hat{lr} = lr \cdot \frac{\sqrt{1 - \beta_2^t}}{1 - \beta_1^t}\end{split}\]

如果不启用 Nesterov:

\[w_t = w_{t-1} - \hat{lr} \cdot \frac{m_t}{\sqrt{v_t} + \epsilon}\]

如果启用 Nesterov:

\[w_t = w_{t-1} - \hat{lr} \cdot \frac{m_t \cdot \beta_1 + (1 - \beta_1) \cdot g_t}{\sqrt{v_t} + \epsilon}\]
输入:
  • m - 一阶矩向量地址(输入/输出)。

  • v - 二阶矩向量地址(输入/输出)。

  • gradient - 梯度向量地址。

  • weight - 权重向量地址(输入/输出)。

  • params - 一其他参数打包。

AdamParam定义如下

 1 typedef struct {
 2    float beta1; //阶矩估计的指数衰减率。
 3    float beta2; //二阶矩估计的指数衰减率
 4    float beta1_power; //:math:`\beta_1^t` 的值(指针形式传入)
 5    float beta2_power; //:math:`\beta_2^t` 的值(指针形式传入)
 6    float eps; // 数值稳定性项 epsilon
 7    float learning_rate; // 学习率
 8    int nesterov; // 是否启用 Nesterov 动量(0: 不启用, 1: 启用)
 9    int start; // 计算的起始索引(包含)
10    int end; // 计算的结束索引(不包含)
11} AdamParam;
输出:
  • m - 更新后的一阶矩。

  • v - 更新后的二阶矩。

  • weight - 更新后的权重。

支持平台:

FT78NE MT7004

备注

  • 支持fp32,fp16类型。

共享存储版本:

void fp_adam_s(float *m, float *v, const float *gradient, float *weight, AdamParam *params, int core_mask)

C调用示例:

 1#include <stdio.h>
 2
 3int main(int argc, char* argv[]) {
 4    // 假设所有数据均位于DDR空间
 5    float* m = (float*)0xC0000000;
 6    float* v = (float*)0xC1000000;
 7    float* gradient = (float*)0xC2000000;
 8    float* weight = (float*)0xC3000000;
 9
10    // 标量参数
11    float beta1 = 0.9f;
12    float beta2 = 0.999f;
13    float beta1_power_val = 0.9f;   // beta1^1
14    float beta2_power_val = 0.999f; // beta2^1
15    float* beta1_power = &beta1_power_val;
16    float* beta2_power = &beta2_power_val;
17    float eps = 1e-8f;
18    float learning_rate = 0.001f;
19    int nesterov = 1;
20
21    int start = 0;
22    int end = 800000; // 元素总数
23    int core_mask = 0xff; // 使用所有核心
24
25    AdamParam params = {
26        .beta1 = beta1,
27        .beta2 = beta2,
28        .beta1_power = beta1_power_val,
29        .beta2_power = beta2_power_val,
30        .eps = eps,
31        .learning_rate = learning_rate,
32        .nesterov = nesterov,
33        .start = 0,
34        .end = 800000
35    };
36
37    fp_adam_s(m, v, gradient, weight, &params, core_mask);
38
39    return 0;
40}

私有存储版本:

void fp_adam_p(float *m, float *v, const float *gradient, float *weight, AdamParam *params)

C调用示例:

 1#include <stdio.h>
 2
 3int main(int argc, char* argv[]) {
 4    // 假设所有数据均位于L2/AM空间
 5    float* m = (float*)0x10820000;
 6    float* v = (float*)0x10830000;
 7    float* gradient = (float*)0x10840000;
 8    float* weight = (float*)0x10850000;
 9
10    float beta1 = 0.9f;
11    float beta2 = 0.999f;
12    float beta1_power_val = 0.9f;
13    float beta2_power_val = 0.999f;
14    float eps = 1e-8f;
15    float learning_rate = 0.001f;
16    int nesterov = 0;
17    int start = 0;
18    int end = 2000;
19
20    AdamParam params = {
21        .beta1 = beta1,
22        .beta2 = beta2,
23        .beta1_power = beta1_power_val,
24        .beta2_power = beta2_power_val,
25        .eps = eps,
26        .learning_rate = learning_rate,
27        .nesterov = nesterov,
28        .start = start,
29        .end = end
30    };
31
32    fp_adam_p(m, v, gradient, weight, &params);
33
34    return 0;
35}